package com.cx.async;

import com.cx.property.JedisProperties;
import com.cx.utils.Const;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.async.RedisAdvancedClusterAsyncCommands;
import io.lettuce.core.sentinel.api.async.RedisSentinelAsyncCommands;

import java.time.Duration;

public class AsyncJedis {

	private RedisAsyncCommands<String, ?> asyncCommands;
	private RedisSentinelAsyncCommands<String, ?> sentinelAsyncCommands;
	private RedisAdvancedClusterAsyncCommands<String, ?> clusterAsyncCommands;


	public AsyncJedis(JedisProperties jedisProperties) {
        if(null != jedisProperties.getPool()) {
            RedisClient redisClient = RedisClient.create("redis://" + jedisProperties.getPassword() + "@" + jedisProperties.getHost() + Const.SP + jedisProperties.getPort() + "/" + jedisProperties.getDatabase());
            redisClient.setOptions(ClusterClientOptions.builder()
                    .topologyRefreshOptions(ClusterTopologyRefreshOptions.builder()
                            .enablePeriodicRefresh(Duration.ofSeconds(jedisProperties.getCacheLevel1Ttl()))
                            .enableAllAdaptiveRefreshTriggers()
                            .build())
                    .build());
            this.asyncCommands = redisClient.connect().async();
        }

        if (null != jedisProperties.getSentinel()) {

        }

        if (null != jedisProperties.getCluster()) {
            RedisClusterClient redisClusterClient = RedisClusterClient.create("redis://" + jedisProperties.getPassword() + "@" + jedisProperties.getHost() + Const.SP + jedisProperties.getPort() + "/" + jedisProperties.getDatabase());
            this.clusterAsyncCommands = redisClusterClient.connect().async();
        }

        if (null != jedisProperties.getShard()) {

        }
	}

	/**
	 * 设置key value
	 * @param key
	 */
//	public boolean set(String key, String value) {
//        List<RedisAdvancedClusterCommands> collect = IntStream.range(0, 20)
//                .mapToObj(i -> clusterAsyncCommands)
//                .collect(toList());
//
//
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("SET".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(value.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return promise.get().equals("OK");
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return false;
//	}
//
//	/**
//	 * 获取key
//	 * @param key
//	 */
//	public <T> T get(String key, Class<T> clazz) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("GET".getBytes());
//		cmd.add(key.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.toObject(promise.get(), clazz);
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return null;
//	}
//
//	/**
//	 * 删除key
//	 * @param key
//	 */
//	public long delete(String key) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("DEL".getBytes());
//		cmd.add(key.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.parse(Long.valueOf(promise.get()));
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return 0;
//	}
//
//	/**
//	 * 批量删除 key
//	 * @param keys
//	 * http://doc.redisfans.com/key/del.html
//	 */
//	public long del(Collection<String> keys) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("DEL".getBytes());
//		cmd.add(String.join(" ", keys.toArray(new String[]{})).getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.parse(Long.valueOf(promise.get()));
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return 0;
//	}
//
//	/**
//	 * 返回给定 key 的剩余生存时间(TTL, time to live)，以秒为单位
//	 * @param key
//	 * http://doc.redisfans.com/key/ttl.html
//	 */
//	public long ttl(String key) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("TTL".getBytes());
//		cmd.add(key.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.parse(Long.valueOf(promise.get()));
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return 0;
//	}
//
//	/**
//	 * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除
//	 * @param key
//	 * http://doc.redisfans.com/key/expire.html
//	 */
//	public boolean expire(String key) {
//		return expire(key, RedisTemplateAdapter.cacheLevel2Ttl());
//	}
//
//	/**
//	 * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除
//	 * @param key
//	 * @param timeout
//	 * http://doc.redisfans.com/key/expire.html
//	 */
//	public boolean expire(String key, long timeout) {
//		if (timeout <= 0) {
//			return false;
//		}
//
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("EXPIRE".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(String.valueOf(timeout).getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.parse(Long.valueOf(promise.get())) > 0;
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return false;
//	}
//
//	/*********************************** Hash ***********************************/
//	/**
//	 * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略
//	 * @param key
//	 * @param hashKey
//	 * http://doc.redisfans.com/hash/hdel.html
//	 * @return
//	 */
//	public long hdel(String key, String... hashKey) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("HDEL".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(String.join(" ", hashKey).getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return JSONParseUtil.parse(Long.valueOf(promise.get()));
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return 0;
//	}
//
//	/**
//	 * 将哈希表 key 中的域 field 的值设为 value
//	 * @param key
//	 * @param hashKey
//	 * @param value
//	 * @param renewExpired 是否更新过期时间(如有)
//	 * http://doc.redisfans.com/hash/hset.html
//	 * @return 1 设置一个新域 | 0 覆盖一个旧域
//	 */
//	public boolean hset(String key, String hashKey, Object value, boolean renewExpired) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("HSET".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(hashKey.getBytes());
//		cmd.add(JSONParseUtil.jsonSerial(value).getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		boolean ret = false;
//		while (promise.isDone()) {
//			try {
//				ret = JSONParseUtil.parse(Long.valueOf(promise.get())) > 0;
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//
//		if (renewExpired || (RedisService.isExpireable(key) && ttl(key) == -1)) {
//			return ret && expire(key);
//		}
//		return ret;
//	}
//
//	/**
//	 * 将哈希表 key 中的域 field 的值设置为 value ，当且仅当域 field 不存在
//	 * @param key
//	 * @param hashKey
//	 * @param value
//	 * @param renewExpired 是否更新过期时间(如有)
//	 * http://doc.redisfans.com/hash/hsetnx.html
//	 * @return 1 设置一个新域 | 0 操作无效，域 field 已存在
//	 */
//	public boolean hsetNx(String key, String hashKey, Object value, boolean renewExpired) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("HSETNX".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(hashKey.getBytes());
//		cmd.add(JSONParseUtil.jsonSerial(value).getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		boolean ret = false;
//		while (promise.isDone()) {
//			try {
//				ret = JSONParseUtil.parse(Long.valueOf(promise.get())) > 0;
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//
//		if (renewExpired || (RedisService.isExpireable(key) && ttl(key) == -1)) {
//			return ret && expire(key);
//		}
//		return ret;
//	}
//
//	/**
//	 * 返回哈希表 key 中给定域 field 的值
//	 * @param key
//	 * @param hashKey
//	 * @param clazz
//	 * http://doc.redisfans.com/hash/hget.html
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public <T> T hget(String key, String hashKey, Class<T> clazz) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("HGET".getBytes());
//		cmd.add(key.getBytes());
//		cmd.add(hashKey.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return (promise.get().equals("nil")) ? null : JSONParseUtil.toObject(promise.get(), clazz);
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return null;
//	}
//
//	/**
//	 * 返回哈希表 key 中，所有的域和值
//	 * @param key
//	 * @param clazz
//	 * http://doc.redisfans.com/hash/hgetall.html
//	 * @return
//	 */
//	@SuppressWarnings("unchecked")
//	public <T> T hgetAll(String key, Class<T> clazz) {
//		BulkStringResultPromise promise = new BulkStringResultPromise(f
//				.channel().eventLoop());
//		List<byte[]> cmd = new ArrayList<byte[]>();
//		cmd.add("HGETALL".getBytes());
//		cmd.add(key.getBytes());
//		f.channel().write(cmd);
//		outputs.add(promise);
//		while (promise.isDone()) {
//			try {
//				return StringUtils.isNotBlank(promise.get()) ? JSONParseUtil.toObject(promise.get(), clazz) : null;
//			} catch (InterruptedException | ExecutionException e) {
//				e.printStackTrace();
//			}
//		}
//		return null;
//	}
//
//	/**
//	 * 查看哈希表 key 中，给定域 field 是否存在
//	 * @param key
//	 * @param hashKey
//	 * http://doc.redisfans.com/hash/hexists.html
//	 * @return
//	 */
//	public boolean hexists(String key, String hashKey) {
//        BulkStringResultPromise promise = new BulkStringResultPromise(f
//                .channel().eventLoop());
//        List<byte[]> cmd = new ArrayList<byte[]>();
//        cmd.add("HEXISTS".getBytes());
//        cmd.add(key.getBytes());
//        cmd.add(hashKey.getBytes());
//        f.channel().write(cmd);
//        outputs.add(promise);
//        while (promise.isDone()) {
//            try {
//                return JSONParseUtil.parse(Integer.valueOf(promise.get())) > 0;
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
//        }
//
//        return false;
//	}
//
//	/**
//	 * 为哈希表 key 中的域 field 的值加上增量 increment
//	 * @param key
//	 * @param hashKey
//	 * @param delta
//	 * @param renewExpired 是否更新过期时间(如有)
//	 * http://doc.redisfans.com/hash/hincrby.html
//	 * @return
//	 */
//	public long hincrby(String key, String hashKey, long delta, boolean renewExpired) {
//        BulkStringResultPromise promise = new BulkStringResultPromise(f
//                .channel().eventLoop());
//        List<byte[]> cmd = new ArrayList<byte[]>();
//        cmd.add("HINCRBY".getBytes());
//        cmd.add(key.getBytes());
//        cmd.add(hashKey.getBytes());
//        cmd.add(String.valueOf(delta).getBytes());
//        f.channel().write(cmd);
//        outputs.add(promise);
//        long ret = 0;
//        while (promise.isDone()) {
//            try {
//                ret = JSONParseUtil.parse(Long.valueOf(promise.get()));
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
//        }
//
//		if (renewExpired || (RedisService.isExpireable(key) && ttl(key) == -1)) {
//			expire(key);
//		}
//		return ret;
//	}
//
//	/**
//	 * 返回哈希表 key 中域的数量
//	 * @param key
//	 * http://doc.redisfans.com/hash/hlen.html
//	 * @return
//	 */
//	public long hlen(String key) {
//        BulkStringResultPromise promise = new BulkStringResultPromise(f
//                .channel().eventLoop());
//        List<byte[]> cmd = new ArrayList<byte[]>();
//        cmd.add("HINCRBY".getBytes());
//        cmd.add(key.getBytes());
//        f.channel().write(cmd);
//        outputs.add(promise);
//        while (promise.isDone()) {
//            try {
//                return JSONParseUtil.parse(Long.valueOf(promise.get()));
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
//        }
//		return 0;
//	}
//
//	/**
//	 * 同时将多个 field-value (域-值)对设置到哈希表 key 中
//	 * @param key
//	 * @param map
//	 * @param renewExpired 是否更新过期时间(如有)
//	 * http://doc.redisfans.com/hash/hmset.html
//	 */
//	public boolean hmset(String key, Map<String, ?> map, boolean renewExpired) {
//        BulkStringResultPromise promise = new BulkStringResultPromise(f
//                .channel().eventLoop());
//        List<byte[]> cmd = new ArrayList<byte[]>();
//        cmd.add("HMSET".getBytes());
//        cmd.add(key.getBytes());
//        map.forEach((k, v) -> {
//            cmd.add((k.getBytes() + " " + JSONParseUtil.jsonSerial(v)).getBytes());
//        });
//        f.channel().write(cmd);
//        outputs.add(promise);
//        boolean ret = false;
//        while (promise.isDone()) {
//            try {
//                ret = promise.get().equals("OK");
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
//        }
//
//		if (renewExpired || (RedisService.isExpireable(key) && ttl(key) == -1)) {
//			return ret && expire(key);
//		}
//		return ret;
//	}
}